const callbacks = []
let pending = false

let microTimerFunc
let macroTimerFunc
let useMacroTask = false

function flushCallbacks () {
    pending = false
    const copies = callbacks.splice(0)
    // 将回调列表清空
    callbacks.length = 0
    for (let i = 0, len = copies.length; i < len; i++) {
        // 执行所有回调
        copies[i]()
    }
}

// 如果支持setImmediate
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
    macroTimerFunc = () => {
        setImmediate(flushCallbacks)
    }
} else if (typeof MessageChannel !== 'undefined' && (
    isNative(MessageChannel) ||
    MessageChannel.toString() === '[object MessageChannelConstructor]'
)) {
    // 如果支持MessageChannel
    const channel = new MessageChannel()
    const port = channel.port2
    channel.port1.onmessage = flushCallbacks
    macroTimerFunc = () => {
        port.postMessage(1)
    }
} else {
    macroTimerFunc = () => {
        setTimeout(flushCallbacks, 0)
    }
}

if (typeof Promise !== 'undefined' && isNative(Promise)) {
    const p = Promise.resolve()
    microTimerFunc = () => {
        p.then(flushCallbacks)
    }
} else {
    microTimerFunc = macroTimerFunc
}

export function withMacroTask (fn) {
    return fn._withTask || (fn._withTask = function () {
        useMacroTask = true
        const res = fn.apply(null, arguments)
        useMacroTask = false
        return res
    })
}

export function nextTick (cb, ctx) {
    let _resolve
    callbacks.push(() => {
        if (cb) {
            cb.call(ctx)
        } else if (_resolve) {
            _resolve(ctx)
        }
    })

    if (!pending) {
        pending = true
        // 强制使用宏任务
        if (useMacroTask) {
            macroTimerFunc()
        } else {
            microTimerFunc()
        }
    }
    // cb不存在同时支持Promise
    if (!cb && typeof Promise !== 'undefined') {
        return new Promise(resolve => {
            _resolve = resolve
        })
    }
}